

/**
 * @file PhaseBiasCalibrate.hpp
 * This class aligns phase with code measurements.
 */

#ifndef PhaseBiasCalibrate_HPP
#define PhaseBiasCalibrate_HPP

//============================================================================
//
//  Dagoberto Salazar - gAGE ( http://www.gage.es ). 2008, 2009, 2011
//
//============================================================================


#include "ProcessingClass.hpp"


namespace gpstk
{

      /** @addtogroup GPSsolutions */
      //@{


      /** This class aligns phase with code measurements.
       *
       * This class is meant to be used with the GNSS data structures objects
       * found in "DataStructures" class.
       *
       * A typical way to use this class follows:
       *
       * @code
       * @endcode
       *
       * The "PhaseBiasCalibrate" object will visit every satellite in the GNSS
       * data structure that is "gRin" and, if an arc change or cycle slip has
       * happened, it will compute the integer phase bias, then remove the integer
       * phase bias from the phase bias for the entire arc.
       *
       * The use of this class is not mandatory; however, it is recommendable
       * given that resulting phase ambiguities are smaller, and it
       * potentially improves the numerical stability of the solver.
       *
       * \warning Be aware that if you change the phase/code pair, you must
       * change the wavelength accordingly.
       *
       * \warning Objects in this class store their internal state, so you
       * MUST NOT use the SAME object to process DIFFERENT data streams.
       *
       * @sa SatArcMarker.hpp, LICSDetector.hpp and MWCSDetector.hpp.
       *
       */
    class PhaseBiasCalibrate : public ProcessingClass
    {
    public:

         /// Default constructor.
        PhaseBiasCalibrate()
            : satSys(SatelliteSystem::GPS),
              phaseType(TypeID::GFIF),
              phaseWavelength(1.0),
              useSatArcs(true), watchCSFlag(TypeID::CSL1)
        {};


         /** Common constructor
          *
          * @param phase            Phase TypeID.
          * @param code             Code TypeID.
          * @param wavelength       Phase wavelength, in meters.
          * @param useArc           Whether satellite arcs will be used or not.
          */
        PhaseBiasCalibrate( const SatelliteSystem::Systems& sys,
                            const TypeID& phase,
                            const double wavelength,
                            bool useArc = true );


        virtual PhaseBiasCalibrate& setSatSystem(const SatelliteSystem::Systems& sys)
        { satSys = sys; return (*this); };


         /// Method to get the phase TypeID being used.
        virtual TypeID getPhaseType() const
        { return phaseType; };


         /** Method to set the phase TypeID to be used.
          *
          * @param phase            Phase TypeID.
          */
        virtual PhaseBiasCalibrate& setPhaseType(const TypeID& phase)
        { 
            phaseType = phase; 
            if(phaseType==TypeID::MW12)
            {
                phaseWavelength = WL12_WAVELENGTH_GPS; 
                resultType = TypeID::MW12Frac;
            }
            else if(phaseType ==TypeID::MW15)
            {
                phaseWavelength = WL15_WAVELENGTH_GPS; 
                resultType = TypeID::MW15Frac;
            }
            else if(phaseType ==TypeID::MW25)
            {
                phaseWavelength = WL25_WAVELENGTH_GPS; 
                resultType = TypeID::MW25Frac;
            }
            else if(phaseType ==TypeID::GFIF)
            {
                phaseWavelength = 1.0; 
                resultType = TypeID::GFIFFrac;
            }

            return (*this); 
        };


         /// Method to get phase wavelength being used.
        virtual double getPhaseWavelength() const
        { return phaseWavelength; };


         /** Method to set the phase wavelength to be used.
          *
          * @param wavelength       Phase wavelength, in meters.
          */
        virtual PhaseBiasCalibrate& setPhaseWavelength(double wavelength);


         /// Method to get if this class will use satellite arcs (true) or
         /// cycle slip flags (false).
        virtual bool getUseSatArc() const
        { return useSatArcs; };


         /** Method to set if this class will use satellite arcs (true) or
          *  cycle slip flags (false).
          *
          * @param useArc           Whether this class will use satellite arcs
          *                         (true) or cycle slip flags (false).
          */
        virtual PhaseBiasCalibrate& setUseSatArc(bool useArc)
        { useSatArcs = useArc; return (*this); };


         /// Method to get the default CS flag type being used.
        virtual TypeID getCSFlag() const
        { return watchCSFlag; };


         /** Method to set the default CS flag type to be used.
          *
          * @param watchFlag     Cycle slip flag to be watched.
          */
        virtual PhaseBiasCalibrate& setCSFlag(const TypeID& watchFlag)
        { watchCSFlag = watchFlag; return (*this); };


         /** Return a satTypeValueMap object, adding the new data generated
          *  when calling this object.
          *
          * @param epoch     Time of observations.
          * @param gData     Data object holding the data.
          */
        virtual satTypeValueMap& Process( const CommonTime& epoch,
                                          satTypeValueMap& gData )
            noexcept(false);



         /** Return a gnssRinex object, adding the new data generated when
          *  calling this object.
          *
          * @param gData    Data object holding the data.
          */
        virtual void Process(commonHeader& comHeader,gnssRinex& gData)
            noexcept(false);


         /** Return a sourceRinex object, adding the new data generated when
          *  calling this object.
          *
          * @param gData    Data object holding the data.
          */
        virtual void Process(commonHeader& comHeader,sourceRinex& gData)
            noexcept(false);


         /// Return a string identifying this object.
        virtual std::string getClassName(void) const;


         /// Destructor
        virtual ~PhaseBiasCalibrate() {};


    private:

        SatelliteSystem::Systems satSys;

         /// TypeID of phase measurement.
        TypeID phaseType;

        TypeID resultType;

         /// Wavelength of phase measurement.
        double phaseWavelength;

         /** Flag indicating if this class will watch for satellite arcs (true)
          *  or cycle slip flags (false).
          */
        bool useSatArcs;


         /// If field 'useSatArcs' is false, cycle slip flag to be watched.
        TypeID watchCSFlag;


         /// Structure used to store SV alignment data.
        struct alignData
        {
            // Default constructor initializing the data in the structure
            alignData() : arcNumber(0.0), offset(0.0) {};

            double arcNumber;       ///< Current arc number
            double offset;          ///< Offset value to be applied
        };


        typedef std::map<SatID, alignData> SatData;
        typedef std::map<SourceID, SatData> SatDataMap;

         /// Map holding the information regarding every satellite
        SatData satData;

         /// Map holding the information for sourceRinex
        SatDataMap satDataMap;


    }; // End of class 'PhaseBiasCalibrate'

    //@}

}  // End of namespace gpstk

#endif   // PhaseBiasCalibrate_HPP
